package com.mgq.juc.queue;

import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;

/**
 * @author MaGuangQi
 * 生产者消费者模式
 * @date 2021-12-16 14:28
 **/
@Slf4j
public class TestMessageQueue {
    public static void main(String[] args) throws InterruptedException {
        MessageQueue list = new MessageQueue(2);
        for (int i = 0; i < 3; i++) {
            int tem = i;
            new Thread(() -> {
                Message message = new Message(tem, "值:" + tem);
                list.put(message);
            }, "生产者").start();
        }

        new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(1000);
                    list.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }, "生产者").start();
    }

}

@Slf4j
class MessageQueue {
    private LinkedList<Message> queues = new LinkedList<>();

    /**
     * 容量
     */
    private int capacity;

    public MessageQueue(int capacity) {
        this.capacity = capacity;
    }

    public Message take() {
        synchronized (queues) {
            while (queues.isEmpty()) {
                try {
                    log.debug("队列已经空了,消费者线程等待");
                    queues.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Message message = queues.removeFirst();
            log.debug("消费消息:{}",message);
            queues.notifyAll();
            return message;
        }

    }

    public void put(Message message) {
        synchronized (queues) {
            while (queues.size() == capacity) {
                try {
                    log.debug("队列已经满了,生产者线程等待");
                    queues.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            queues.addLast(message);
            log.debug("生产消息:{}",message);
            queues.notifyAll();
        }
    }
}

final class Message {
    private int id;
    private Object value;

    public Message(int id, Object value) {
        this.id = id;
        this.value = value;
    }
}
